package main

import "fmt"

/*
一 简介
	数组是一段长度固定的连续内存区域，拥有0个或多个（不超过数组长度）相同数据类型的数据项序列，其中元素
	类型支持任意内置类型这种类型可以是任意的原始类型例如:整数、字符串、或者自定义类型。
	数组在声明的时候（使用 [长度]类型 ） 进行声明的时候必须指定长度，可以修改数组元素，但是不可以修改数组长度。
	指针数组 [n]*T   数组指针*[n]T
二 优势
三 数组声明
	Go声明数组需要指定元素类型以及元素个数，语法格式如下：
		var name [SIZE]type
	以上是一维数组的定义方式：
	多维数组的声明：
	var name[SIZE1] [SIZE2] ...[SIZEN]]type
*/

func main() {
	//四 数组的初始化
	//1.声明的同时初始化
	var balance = [5]float32{1000.0, 2.0, 3.4, 7.0, 50.0}
	fmt.Println(balance)
	//2.使用赋值操作符声明初始化数组
	//一维数组的声明
	balance1 := [5]float32{1000.0, 2.0, 3.4, 7.0, 50.0}
	fmt.Println(balance1)
	//多维数组的声明
	a := [3][4]int{
		{0, 1, 2, 3},
		{4, 5, 6, 7},
		{8, 9, 10, 11},
	}
	fmt.Println(a)
	fmt.Println(a[0][0]) //数组中第一个元素的索引为0
	//    特殊情况说明：
	//    1.数组的长度不确定
	//    如果数组的长度不确定，可以使用 ... 代替数组的长度编译器会根据元素个数自行推断出数组的长度
	var balance2 = [...]float32{1000.0, 2.0, 3.4, 7.0, 50.0}
	fmt.Println(len(balance2)) //5
	//    或
	balance3 := [...]float32{1000.0, 2.0, 3.4, 7.0}
	fmt.Println(len(balance3)) //4
	//	  2.只初始化个别元素（通过下标）
	//	  如果设置了数组的长度，我们还可以通过指定下标来初始化数组
	balance4 := [5]float32{1: 1.1, 2: 2.0} //将索引为1和索引为2的进行初始化
	fmt.Println(balance4)
	/*
		初始化数组中{}的元素个数不能大于[]中的数字。
		如果忽略[] 中的数字不设置数组的大小，Go语言会根据元素的个数来设置数组的大小。
	*/
	/*
			3.一维数组初始化方法总结
				全局变量：
				var arr0 [5]int = [5]int{1, 2, 3}
				var arr1 = [5]int{1, 2, 3, 4, 5}
				var arr2 = [...]int{1, 2, 3, 4, 5, 6}
				var str = [5]string{3: "hello world", 4: "tom"}
				局部变量：
				a := [3]int{1, 2}           // 未初始化元素值为 0。
				b := [...]int{1, 2, 3, 4}   // 通过初始化值确定数组长度。
				c := [5]int{2: 100, 4: 200} // 使用索引号初始化元素。
				d := [...]struct {
					name string
					age  uint8
				}{
					{"user1", 10}, // 可省略元素类型。
					{"user2", 20}, // 别忘了最后一行的逗号。
				}
			4.多维数组初始化方法总结：
				全局变量：
				var arr0 [5][3]int
				var arr1 [2][3]int = [...][3]int{{1, 2, 3}, {7, 8, 9}}
				局部变量：
				a := [2][3]int{{1, 2, 3}, {4, 5, 6}}
				b := [...][2]int{{1, 1}, {2, 2}, {3, 3}} // 第 2 纬度不能用 "..."。

		注意数组的第二维度不能使用 ...
	*/

	//五 数组元素的访问
	//数组元素的访问可以通过索引(位置) 来读取。格式为数组名后加中括号，中括号中为索引的值。
	//例子：var salary float32 = balance[9]
	//多维数组的遍历：
	var f [2][3]int = [...][3]int{{1, 2, 3}, {7, 8, 9}}

	for k1, v1 := range f {
		for k2, v2 := range v1 {
			fmt.Printf("(%d,%d)=%d ", k1, k2, v2)
		}
		fmt.Println()
	}
	//六 获取数组的长度：内置函数：len() 和 cap() 都返回数组的长度（元素数量）
	//七 向函数传递数组
	//	如果你想向函数中传递数组参数，你需要在函数定义时，声明形参为数组，我们可以通过以下两种方式来声明：
	/*
		方式一：形参未设定数组大小
		void myFunction(param []int)
		{

		}
		方式二：形参未设置数组大小
		void myFunction(param []int)
		{

		}
	*/
	/*
			我们知道Go 语言中的数组是值类型，赋值和传参会复制整个数组的值，而不是指针/地址，因此函数内改变的是副本的值，不改变本身的值。
			与C数组变量隐式作为指针使用不同，Go数组是值类型，赋值和函数传参操作都会复制整个数组的数据。
			注意：值拷贝行为会造成性能问题，通常建议使用slice,或者数组指针
			通常还是建议：使用 slice，或 数组指针 来给函数传参。
		总结：想通过函数调用改变数内容的两种方式
			1.return + 赋值
			2.用slice,或数组指针来传参（推荐）
	*/

}
